/**
 *
 *  Util.Plot.TimeSeriesAppWindow, V0.7
 *
 *  Based on ptplot example. See below.
 *
 *  @author Michael Liljenstam
 *
 */


/* Top-level window containing a plotter.

 Copyright (c) 1998-1999 The Regents of the University of California.
 All rights reserved.
 Permission is hereby granted, without written agreement and without
 license or royalty fees, to use, copy, modify, and distribute this
 software and its documentation for any purpose, provided that the above
 copyright notice and the following two paragraphs appear in all copies
 of this software.

 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 SUCH DAMAGE.

 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
 ENHANCEMENTS, OR MODIFICATIONS.

                                        PT_COPYRIGHT_VERSION_2
                                        COPYRIGHTENDKEY
@ProposedRating Yellow (cxh@eecs.berkeley.edu)
@AcceptedRating Yellow (cxh@eecs.berkeley.edu)
*/

package SSF.Util.Plot;

//import ptolemy.plot.*;
//import ptolemy.plot.PlotPoint;
import ptolemy.gui.*;


import java.awt.*;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import java.awt.event.*;
import java.io.*;
import java.net.URL;
import java.util.StringTokenizer;
import java.util.Vector;

//////////////////////////////////////////////////////////////////////////
//// TimeSeriesAppWindow
/**


Split from TimeSeriesWindow into a separate, more "heavy weight" subclass.
@author mod's by Michael Liljenstam

@see ptolemy.plot.PlotFrame
@see ptolemy.plot.Plot
@see ptolemy.plot.PlotBox
@author Christopher Hylands and Edward A. Lee
@version $Id: TimeSeriesAppWindow.java,v 1.6 2003/02/13 19:34:09 mili Exp $
*/
public class TimeSeriesAppWindow extends TimeSeriesWindow {


    ///////////////////////////////////////////////////////////////////
    ////                     constructors & methods                ////

    /** 
     *  Create a time-series plot window for a separate application.
     *  (more menu options).
     *  
     *  
     */
    //    public TimeSeriesAppWindow(String title, MultiPlotBox[] plotArgs,
    //			       int plotHeights) 
    public TimeSeriesAppWindow(String title, TimeSeriesComponent plot)
	throws Exception {

	// invoke the base class constructor and pass in the argument a Plot
	// object. This makes sure that the plot field is an instance of
	// Plot class.
	super(title);


        add("Center", plot); // add as a child object
	_plot = plot;

	setSize(_plot.getSize()); // why is this necessary?

	addMenus();

	addClosingListenerAndDisplay();
    }

    ///////////////////////////////////////////////////////////////////
    ////                         public methods                    ////

    /**
     *  Signal that the end of the live plotting has been reached.
     *  Triggers internal state-transition.
     */

    public void signalEndOfPlot()
    {
	// set plots to stopped
	//	for (int i=0; i<plots.length; i++)
	//	    ((LivePlotter) plots[i]).stopPlot();
	_plot.stopAll();

	// enable options
	_plotMenu.getItem(PM_FILL_ITEM).setEnabled(true); // Fill
	_plotMenu.getItem(PM_START_ITEM).setEnabled(true); // Restart
	// disable options
	_plotMenu.getItem(PM_STOP_ITEM).setEnabled(false); // Stop
	_plotMenu.getItem(PM_CONT_ITEM).setEnabled(false); // Continue
    }


    ///////////////////////////////////////////////////////////////////
    ////                         public variables                  ////


    ///////////////////////////////////////////////////////////////////
    ////                         protected variables               ////

    /** @serial File menu for this frame. */
    protected Menu _fileMenu = new Menu("File");

    /** @serial Plot menu for this frame. */
    protected Menu _plotMenu = new Menu("Plot");

    /** @serial directory that contains the input file. */
    protected String _directory = null;

    /** @serial name of the input file. */
    protected String _filename = null;

    // enumeration of Plot menu items.
    protected final int    PM_FILL_ITEM =  0;
    protected final int    PM_START_ITEM = 1;
    protected final int    PM_STOP_ITEM =  2;
    protected final int    PM_CONT_ITEM =  3;
    protected final int    PM_HELP_ITEM =  4;
    protected final int    PM_ABOUT_ITEM = 5;


    ///////////////////////////////////////////////////////////////////
    ////                         protected methods                 ////


    protected void addMenus() {

        // File menu
        MenuItem[] fileMenuItems = {
            // FIXME: These shortcuts are not right.
            new MenuItem("SaveAs", new MenuShortcut(KeyEvent.VK_A)),
            new MenuItem("Export", new MenuShortcut(KeyEvent.VK_E)),
            new MenuItem("Print", new MenuShortcut(KeyEvent.VK_P)),
            new MenuItem("Close", new MenuShortcut(KeyEvent.VK_W)),
        };
        FileMenuListener fml = new FileMenuListener();
        // Set the action command and listener for each menu item.
        for(int i = 0; i < fileMenuItems.length; i++) {
            fileMenuItems[i].setActionCommand(fileMenuItems[i].getLabel());
            fileMenuItems[i].addActionListener(fml);
            _fileMenu.add(fileMenuItems[i]);
	    // disable all options except "close" initially
	    if (i != 3)
		fileMenuItems[i].setEnabled(false);
	    else
		fileMenuItems[i].setEnabled(true);
        }
        _menubar.add(_fileMenu);

        // Plot menu
        MenuItem[] plotMenuItems = {
            // FIXME: These shortcuts are not right.
            new MenuItem("Fill", new MenuShortcut(KeyEvent.VK_F)),
            new MenuItem("Start", new MenuShortcut(KeyEvent.VK_R)),
            new MenuItem("Stop", new MenuShortcut(KeyEvent.VK_S)),
            new MenuItem("Continue", new MenuShortcut(KeyEvent.VK_C)),
            new MenuItem("Help", new MenuShortcut(KeyEvent.VK_H)),
            new MenuItem("About", null),
        };
        PlotMenuListener sml = new PlotMenuListener();
        // Set the action command and listener for each menu item.
        for(int i = 0; i < plotMenuItems.length; i++) {
            plotMenuItems[i].setActionCommand(
                    plotMenuItems[i].getLabel());
            plotMenuItems[i].addActionListener(sml);
            _plotMenu.add(plotMenuItems[i]);

	    // disable all options except "About", "Help", and "Start" 
	    // initially
	    if (i < 4 && i != 1) {
		plotMenuItems[i].setEnabled(false);
	    }
        }
        _menubar.add(_plotMenu);

        setMenuBar(_menubar);
    }

    protected void _about() {
        JOptionPane.showMessageDialog(this,
                "TimeSeriesWindow class\n" +
                "By: Edward A. Lee, eal@eecs.berkeley.edu " +
                "and Christopher Hylands, cxh@eecs.berkeley.edu\n" +
                "Version 3.1, Build: $Id: TimeSeriesAppWindow.java,v 1.6 2003/02/13 19:34:09 mili Exp $\n\n"+
                "For more information, see\n" +
                "http://ptolemy.eecs.berkeley.edu/java/ptplot\n\n" +
                "Copyright (c) 1997-1999, " +
                "The Regents of the University of California.",
                "About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
    }

    /** Close the window.
     */
    protected void _close() {
        dispose();
    }


    /** Query the user for a filename and export the plot to that file.
     *  Currently, the only supported format is EPS.
     */
    protected void _export() {
        FileDialog filedialog = new FileDialog(this, "Export EPS to...");
        if (_directory != null) {
            filedialog.setDirectory(_directory);
        }
        filedialog.setFile("plot.eps");
        filedialog.setVisible(true);
        String filename = filedialog.getFile();
        if (filename == null) return;
        String directory = filedialog.getDirectory();
        File file = new File(directory, filename);
        try {
            FileOutputStream fout = new FileOutputStream(file);
	    //	    for (int i=0; i<plots.length; i++)
	    //		plots[i].export(fout);
	    _plot.exportAll(fout);
        } catch (IOException ex) {
            Message msg = new Message("Error exporting plot: " + ex);
        }
    }

    /** Display more detailed information than given by _about().
     */
    protected void _help() {
        JOptionPane.showMessageDialog(this,
                "TimeSeriesWindow is a plot in a top-level window.\n" +
                "  File formats understood: Ptplot ASCII.\n" +
                "  Left mouse button: Zooming.",
                "About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
    }

    /** Print the plot.
     */
    protected void _print() {
        // The awt uses properties to set the defaults:
        // awt.print.destination   - can be "printer" or "file"
        // awt.print.printer       - print command
        // awt.print.fileName      - name of the file to print
        // awt.print.numCopies     - obvious
        // awt.print.options       - options to pass to the print command
        // awt.print.orientation   - can be "portrait" or "landscape"
        // awt.print.paperSize     - can be "letter", "legal", "executive"
        //                           or "a4"

        // Accept the defaults... But if you want to change them,
        // do something like this...
        // Properties newprops = new Properties();
        // newprops.put("awt.print.destination", "file");
        // newprops.put("awt.print.fileName", _outputFile);
        // PrintJob printjob = getToolkit().getPrintJob(this,
        //      getTitle(), newprops);
        PrintJob printjob = getToolkit().getPrintJob(this,
                getTitle(), null);
        if (printjob != null) {
            try {
                Graphics printgraphics = printjob.getGraphics();
                if (printgraphics != null) {
                    // Print only the plot frame.
                    try {
			//			for (int i=0; i<plots.length; i++)
			//			    plots[i].printAll(printgraphics);
			_plot.printAll(printgraphics);
                    } finally {
                        printgraphics.dispose();
                    }
                }
            } finally {
                printjob.end();
            }
        }
    }


    /** Save the plot to the current file, determined by the _directory
     *  and _filename protected variables.
     */
    protected void _save() {
        if (_filename != null) {
            File file = new File(_directory, _filename);
            try {
                FileOutputStream fout = new FileOutputStream(file);
		/** FIXME */
		//                plot.write(fout);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(this,
                "Error writing file:\n" + ex.toString(),
                "Ptolemy Plot Error", JOptionPane.WARNING_MESSAGE);
            }
        } else {
            _saveAs();
        }
    }

    /** Query the user for a filename and save the plot to that file.
     */
    protected void _saveAs() {
        FileDialog filedialog = new FileDialog(this, "Save plot as...");
        if (_directory != null) {
            filedialog.setDirectory(_directory);
        }
        filedialog.setFile("plot.xml");
        filedialog.setVisible(true);
        _filename = filedialog.getFile();
        if (_filename == null) return;
        _directory = filedialog.getDirectory();
        _save();
    }


    //
    // plot menu
    // 

    protected void _start() { // for options "Start" and "Restart"
	if (_state == INIT) {
	    //	    for (int i=0; i<plots.length; i++) {
	    //		((LivePlotter) plots[i]).startPlot();
	    //	    }
	    _plot.startAll();
	    // enable "Stop"
	    _plotMenu.getItem(PM_STOP_ITEM).setEnabled(true);
	    // disable "Start" and change label to "Restart"
	    _plotMenu.getItem(PM_START_ITEM).setEnabled(false);
	    _plotMenu.getItem(PM_START_ITEM).setLabel("Reset");
	    
	    // change state
	    _state = RUNNING;
	} else {
	    //	    for (int i=0; i<plots.length; i++) {
	    //		((LivePlotter) plots[i]).resetPlot();
	    //	    }
	    _plot.resetAll();
	    // change label to "Start"
	    _plotMenu.getItem(PM_START_ITEM).setLabel("Start");

	    // disable options
	    _plotMenu.getItem(PM_FILL_ITEM).setEnabled(false); // Fill
	    _plotMenu.getItem(PM_CONT_ITEM).setEnabled(false); // Continue
	    
	    // change state
	    _state = INIT;
	}
    }

    protected void _stop() {
	//	for (int i=0; i<plots.length; i++)
	//	    ((LivePlotter) plots[i]).stopPlot();
	_plot.stopAll();
	// enable options
	_plotMenu.getItem(PM_FILL_ITEM).setEnabled(true); // Fill
	_plotMenu.getItem(PM_START_ITEM).setEnabled(true); // Reset
	_plotMenu.getItem(PM_CONT_ITEM).setEnabled(true); // Continue
	// disable "Stop"
	_plotMenu.getItem(PM_STOP_ITEM).setEnabled(false);
    }

    protected void _continue() {
	//	for (int i=0; i<plots.length; i++)
	//	    ((LivePlotter) plots[i]).continuePlot();
	_plot.continueAll();
	// enable "Stop"
	_plotMenu.getItem(PM_STOP_ITEM).setEnabled(true);
	// disable options
	_plotMenu.getItem(PM_START_ITEM).setEnabled(false); // Reset
	_plotMenu.getItem(PM_CONT_ITEM).setEnabled(false); // Continue
	_plotMenu.getItem(PM_FILL_ITEM).setEnabled(false); // Fill
    }


    // event listeners

    /**
     *  Add closing window listener and display window.
     *  (finish setup.) Overrides listener in TimeSeriesWindow.
     */

    protected void addClosingListenerAndDisplay() {

	// Handle window closing by exiting the application.
	addWindowListener(new WindowAdapter() {
		public void windowClosing(WindowEvent e) {
		    _close();
		    System.exit(0);
		}
	    });
	setVisible(true);
    }


    ///////////////////////////////////////////////////////////////////
    ////                         private methods                   ////



    ///////////////////////////////////////////////////////////////////
    ////                         inner classes                     ////

    class FileMenuListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            MenuItem target = (MenuItem)e.getSource();
            String actionCommand = target.getActionCommand();
	    if (actionCommand.equals("SaveAs")) _saveAs();
            else if (actionCommand.equals("Export")) _export();
            else if (actionCommand.equals("Print")) _print();
            else if (actionCommand.equals("Close")) {
		_close();
		System.exit(0);
	    }
        }
    }

    class PlotMenuListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            MenuItem target = (MenuItem)e.getSource();
            String actionCommand = target.getActionCommand();
            if (actionCommand.equals("About")) {
                _about();
            } else if (actionCommand.equals("Help")) {
                _help();
            } else if (actionCommand.equals("Fill")) {
		//		for (int i=0; i<plots.length; i++)
		//		    plots[i].fillPlot();
		_plot.fillAll();
            } else if (actionCommand.equals("Start")) {
		_start();
            } else if (actionCommand.equals("Stop")) {
		_stop();
            } else if (actionCommand.equals("Continue")) {
		_continue();
            }
        }
    }
}
